﻿using DevExpress.XtraPrinting.BarCode;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;

namespace HenrryTools.WinFormTools
{
    public partial class ScanCodeWinForm : Form
    {
        public ScanCodeWinForm()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ScanCodeWinForm_Load(object sender, EventArgs e)
        {
            DefalutCBBoxValue();
        }
        /// <summary>
        /// 默认赋值CBBox值
        /// </summary>
        public void DefalutCBBoxValue()
        {
            int MaxNumber = 99;//默认值
            object[] DefalueValue = new object[98];
            for (var i = 1; i < MaxNumber; i++)
            {
                DefalueValue[i - 1] = i;
            }
            CBBoxWidth.Items.AddRange(DefalueValue);
            CBBoxHeight.Items.AddRange(DefalueValue);
            CBBoxMargin.Items.AddRange(DefalueValue);
        }

        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="text">内容</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="margin">边距</param>
        /// <param name="characterSet">编码</param>
        /// <returns></returns>
        public void Generate1ScanCode(string text, int width, int height, int margin, string characterSet)
        {
            try
            {
                BarcodeWriter writer = new BarcodeWriter();
                writer.Format = BarcodeFormat.QR_CODE;
                QrCodeEncodingOptions options = new QrCodeEncodingOptions()
                {
                    DisableECI = true,//设置内容编码
                    CharacterSet = characterSet,  //设置二维码的宽度和高度
                    Width = width,
                    Height = height,
                    Margin = margin//设置二维码的边距,单位不是固定像素
                };

                writer.Options = options;
                Bitmap map = writer.Write(text);
                PtBoxScanCode.Image = map;
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常:" + ex.Message);
            }
        }

        /// <summary>
        /// 生成一维条形码
        /// </summary>
        /// <param name="text">内容</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <returns></returns>
        public void Generate2(string text, int width, int height, int margin, string barcodeFormat)
        {
            try
            {
                BarcodeWriter writer = new BarcodeWriter();
                //使用ITF 格式，不能被现在常用的支付宝、微信扫出来
                //如果想生成可识别的可以使用 CODE_128 格式
                //writer.Format = BarcodeFormat.ITF;
                writer.Format = BarcodeFormat.CODE_39;
                switch (barcodeFormat)
                {
                    case "AZTEC":
                        writer.Format = BarcodeFormat.AZTEC;
                        break;
                    case "CODABAR":
                        writer.Format = BarcodeFormat.CODABAR;
                        break;
                    case "CODE_93":
                        writer.Format = BarcodeFormat.CODE_93;
                        break;
                    case "CODE_39":
                        writer.Format = BarcodeFormat.CODE_39;
                        break;
                    case "CODE_128":
                        writer.Format = BarcodeFormat.CODE_128;
                        break;
                    case "DATA_MATRIX":
                        writer.Format = BarcodeFormat.DATA_MATRIX;
                        break;
                    case "EAN_8":
                        writer.Format = BarcodeFormat.EAN_8;
                        break;
                    case "EAN_13":
                        writer.Format = BarcodeFormat.EAN_13;
                        break;
                    case "ITF":
                        writer.Format = BarcodeFormat.ITF;
                        break;
                    case "MAXICODE":
                        writer.Format = BarcodeFormat.MAXICODE;
                        break;
                    case "PDF_417":
                        writer.Format = BarcodeFormat.PDF_417;
                        break;
                    case "QR_CODE":
                        writer.Format = BarcodeFormat.QR_CODE;
                        break;
                    case "RSS_14":
                        writer.Format = BarcodeFormat.RSS_14;
                        break;
                    case "RSS_EXPANDED":
                        writer.Format = BarcodeFormat.RSS_EXPANDED;
                        break;
                    case "UPC_E":
                        writer.Format = BarcodeFormat.UPC_E;
                        break;
                    case "UPC_EAN_EXTENSION":
                        writer.Format = BarcodeFormat.UPC_EAN_EXTENSION;
                        break;
                    case "MSI":
                        writer.Format = BarcodeFormat.MSI;
                        break;
                    case "PLESSEY":
                        writer.Format = BarcodeFormat.PLESSEY;
                        break;
                    case "IMB":
                        writer.Format = BarcodeFormat.IMB;
                        break;
                    case "PHARMA_CODE":
                        writer.Format = BarcodeFormat.PHARMA_CODE;
                        break;
                    case "All_1D":
                        writer.Format = BarcodeFormat.All_1D;
                        break;
                }

                EncodingOptions options = new EncodingOptions()
                {
                    Width = width,
                    Height = height,
                    Margin = margin
                };
                writer.Options = options;
                Bitmap map = writer.Write(text);
                PtBoxScanCode.Image = map;
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常:" + ex.Message);
            }
        }
        /// <summary>
        /// 生成带Logo的二维码
        /// </summary>
        /// <param name="text">内容</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        public void Generate3(string text, int width, int height, string file)
        {
            try
            {
                //Logo 图片
                //string logoPath = System.AppDomain.CurrentDomain.BaseDirectory + @"\img\logo.png";
                Bitmap logo = new Bitmap(file);
                //构造二维码写码器
                MultiFormatWriter writer = new MultiFormatWriter();
                Dictionary<EncodeHintType, object> hint = new Dictionary<EncodeHintType, object>();
                hint.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
                hint.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Level4);
                hint.Add(EncodeHintType.MARGIN, 3);//旧版本不起作用，需要手动去除白边

                //生成二维码
                BitMatrix bm = writer.encode(text, BarcodeFormat.QR_CODE, width + 30, height + 30, hint);
                bm = deleteWhite(bm);
                BarcodeWriter barcodeWriter = new BarcodeWriter();
                Bitmap map = barcodeWriter.Write(bm);

                //获取二维码实际尺寸（去掉二维码两边空白后的实际尺寸）
                int[] rectangle = bm.getEnclosingRectangle();

                //计算插入图片的大小和位置
                int middleW = Math.Min((int)(rectangle[2] / 3), logo.Width);
                int middleH = Math.Min((int)(rectangle[3] / 3), logo.Height);
                int middleL = (map.Width - middleW) / 2;
                int middleT = (map.Height - middleH) / 2;

                Bitmap bmpimg = new Bitmap(map.Width, map.Height, PixelFormat.Format32bppArgb);
                using (Graphics g = Graphics.FromImage(bmpimg))
                {
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    g.DrawImage(map, 0, 0, width, height);
                    //白底将二维码插入图片
                    g.FillRectangle(Brushes.White, middleL, middleT, middleW, middleH);
                    g.DrawImage(logo, middleL, middleT, middleW, middleH);
                }
                PtBoxScanCode.Image = bmpimg;
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常:" + ex.Message);
            }

        }

        /// <summary>
        /// 删除默认对应的空白
        /// </summary>
        /// <param name="matrix"></param>
        /// <returns></returns>
        private static BitMatrix deleteWhite(BitMatrix matrix)
        {
            int[] rec = matrix.getEnclosingRectangle();
            int resWidth = rec[2] + 1;
            int resHeight = rec[3] + 1;

            BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
            resMatrix.clear();
            for (int i = 0; i < resWidth; i++)
            {
                for (int j = 0; j < resHeight; j++)
                {
                    if (matrix[i + rec[0], j + rec[1]])
                        resMatrix[i, j] = true;
                }
            }
            return resMatrix;
        }
        /// <summary>
        /// 条形码格式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox5_SelectedIndexChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            Image img = PtBoxScanCode.Image;
            if (img != null)
            {
                SaveFileDialog sFD = new SaveFileDialog();
                sFD.Filter = "*.png|*.png";
                if (sFD.ShowDialog() == DialogResult.OK)
                {
                    Bitmap bmap = new Bitmap(img, img.Width, img.Height);
                    bmap.Save(sFD.FileName);
                    MessageBox.Show("保存成功！");
                }
            }
            else
            {
                MessageBox.Show("您还没有生成二维码！");
            }
        }
        /// <summary>
        /// 生成按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnScanCode_Click(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 判断是什么码
        /// </summary>
        public void Send()
        {
            if (radioScanCode.Checked)
            {
                GetScanCode();
            }
            else if (radioGenerate.Checked)
            {
                GetGenerate();
            }
            else if (radioScanLogoCode.Checked)
            {
                getScanLogoCode();
            }
        }
        /// <summary>
        /// 二维码
        /// </summary>
        public void GetScanCode()
        {
            if (string.IsNullOrWhiteSpace(txtRoot.Text))
            {
                MessageBox.Show("你输入的内容为空!");
                return;
            }
            if (string.IsNullOrWhiteSpace(CBBoxWidth.Text) || string.IsNullOrWhiteSpace(CBBoxHeight.Text) || string.IsNullOrWhiteSpace(CBBoxMargin.Text))
            {
                MessageBox.Show("高度、宽度、边距不能为空!");
                return;
            }
            if (string.IsNullOrWhiteSpace(CBBoxTxtCode.Text))
            {
                MessageBox.Show("二维码编码为空!");
                return;
            }
            Generate1ScanCode(txtRoot.Text, int.Parse(CBBoxWidth.Text) * 30, int.Parse(CBBoxHeight.Text) * 30, int.Parse(CBBoxMargin.Text), CBBoxTxtCode.Text);
        }
        /// <summary>
        /// 条形码
        /// </summary>
        public void GetGenerate()
        {
            if (string.IsNullOrWhiteSpace(txtRoot.Text))
            {
                MessageBox.Show("你输入的内容为空!");
                return;
            }
            if (string.IsNullOrWhiteSpace(CBBoxHeight.Text))
            {
                MessageBox.Show("宽度不能为空!");
                return;
            }
            if (string.IsNullOrWhiteSpace(CBBoxBarcodeFormat.Text))
            {
                MessageBox.Show("条形码格式为空!");
                return;
            }
            Generate2(txtRoot.Text, int.Parse(CBBoxWidth.Text), 70, 10, CBBoxBarcodeFormat.Text);
        }
        /// <summary>
        /// QRCode
        /// </summary>
        public void getScanLogoCode()
        {
            if (string.IsNullOrWhiteSpace(txtRoot.Text))
            {
                MessageBox.Show("你输入的内容为空!");
                return;
            }
            if (string.IsNullOrWhiteSpace(CBBoxWidth.Text) || string.IsNullOrWhiteSpace(CBBoxHeight.Text))
            {
                MessageBox.Show("高度、宽度不能为空!");
                return;
            }
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = false;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件夹";
            dialog.Filter = "图像文件(*.gif;*.jpg;*.jpeg;*.png;*.psd)|*.gif;*.jpg;*.jpeg;*.png;*.psd";
            string file = string.Empty;
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                file = dialog.FileName;
                Generate3(txtRoot.Text, int.Parse(CBBoxWidth.Text) * 10, int.Parse(CBBoxHeight.Text) * 10, file);
            }

        }

        /// <summary>
        /// 解码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDeCode_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = false;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件夹";
            dialog.Filter = "图像文件(*.gif;*.jpg;*.jpeg;*.png;*.psd)|*.gif;*.jpg;*.jpeg;*.png;*.psd";
            string file = string.Empty;
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                file = dialog.FileName;
            }
            //图片路径
            string imgPath = file;

            //解码通用类
            IBarcodeReader reader = new BarcodeReader();
            Bitmap bmp = new Bitmap(imgPath);
            Result result = reader.Decode(bmp);
            bmp.Dispose();
            if (result != null)
            {
                string text = result.Text; //条码内容
                string foramt = result.BarcodeFormat.ToString(); //条码类型
                txtRoot.Text = "条码内容:" + text + "\n条码类型:" + foramt;
            }
        }
        /// <summary>
        /// 文本监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtRoot_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 宽度监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxWidth_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 高度监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxHeight_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 边距监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxMargin_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 二维码格式监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxTxtCode_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 条形码格式监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxBarcodeFormat_TextChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radioScanCode_CheckedChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 条形码监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radioGenerate_CheckedChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// QRCODE监控
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radioScanLogoCode_CheckedChanged(object sender, EventArgs e)
        {
            //getScanLogoCode();
        }
        /// <summary>
        /// 宽度
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxWidth_SelectedIndexChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 高度
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxHeight_SelectedIndexChanged(object sender, EventArgs e)
        {
            Send();
        }
        /// <summary>
        /// 边距
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CBBoxMargin_SelectedIndexChanged(object sender, EventArgs e)
        {
            Send();
        }
    }
}
